#include <sxQViewportFrame.h>
#include <sxQViewport.h>
#include <QToolButton>
#include <QToolBar>

/*
 * Constants that define the height of the toolbar and size of each icon used
 * to represent a button on this toolbar. For the images to appear correctly
 * they must be provided in the same size as those that already exist.
 */
const static unsigned int TOOLBAR_HEIGHT = 23;
const static unsigned int TOOLBAR_ICON_SIZE = 17;

Sx::QtInterface::QViewportFrame::QViewportFrame(QWidget* parent, QViewport* viewport, const std::shared_ptr<ViewportController>& controller, Qt::WFlags flags) : 
	QWidget(parent, flags) {

	if ( viewport == nullptr ) {
		std::cerr << "[QViewportFrame:QViewportFrame] Error: Cannot assign controller to nullptr viewport." << std::endl;
		std::cerr << "  The viewport will be created without a controller." << std::endl;
	}
	else {
		this->viewport = viewport;
		this->viewport->setController(controller);
		this->viewport->setParent(this);
	}

	this->setFocusPolicy(Qt::ClickFocus);
	this->toolbar = nullptr;
	this->toolbarHeight = TOOLBAR_HEIGHT;
	this->toolbarIconSize = TOOLBAR_ICON_SIZE;
}

Sx::QtInterface::QViewportFrame::~QViewportFrame() {}

bool Sx::QtInterface::QViewportFrame::update() {
	if ( this->viewport == nullptr ) return false;
	this->viewport->update();
	return true;

}
bool Sx::QtInterface::QViewportFrame::update(float dt) {
	if ( this->viewport == nullptr ) return false;
	this->viewport->update(dt);
	return true;
}

bool Sx::QtInterface::QViewportFrame::reRender() const {
	if ( this->viewport == nullptr ) return false;
	this->viewport->reRender();
	return true;
}

bool Sx::QtInterface::QViewportFrame::updateAndRender() {
	if ( this->viewport == nullptr ) return false;
	this->viewport->updateAndRender();
	return true;
}

bool Sx::QtInterface::QViewportFrame::setController(const std::shared_ptr<ViewportController>& controller) {
	if ( this->viewport == nullptr ) {
		std::cerr << "[QViewportFrame:setController] Error: Cannot set controller of nullptr viewport." << std::endl;
		return false;
	}

	this->viewport->setController(controller);
	return true;
}

std::shared_ptr<Sx::Interface::ViewportController> Sx::QtInterface::QViewportFrame::getController() const {
	if ( this->viewport == nullptr ) {
		std::cerr << "[QViewportFrame:getController] Error: Cannot retrieve controller from nullptr viewport." << std::endl;
		return nullptr;
	}

	return this->viewport->getController();
}

void Sx::QtInterface::QViewportFrame::setToolBarHeight(unsigned int height) {
	this->toolbarHeight = height;
}

void Sx::QtInterface::QViewportFrame::setToolBarIconSize(unsigned int size) {
	this->toolbarIconSize = size;
}

unsigned int Sx::QtInterface::QViewportFrame::getToolBarHeight() const {
	return this->toolbarHeight;
}

unsigned int Sx::QtInterface::QViewportFrame::getToolBarIconSize() const {
	return this->toolbarIconSize;
}

bool Sx::QtInterface::QViewportFrame::setClearColor(const Color3f& color) {
	if ( this->viewport == nullptr ) return false;
	return this->viewport->setClearColor(color);
}

bool Sx::QtInterface::QViewportFrame::setClearColor(const Color4f& color) {
	if ( this->viewport == nullptr ) return false;
	return this->viewport->setClearColor(color);
}

bool Sx::QtInterface::QViewportFrame::setClearColor(float r, float g, float b) {
	if ( this->viewport == nullptr ) return false;
	return this->viewport->setClearColor(r, g, b);
}

bool Sx::QtInterface::QViewportFrame::setClearColor(float r, float g, float b, float a) {
	if ( this->viewport == nullptr ) return false;
	return this->viewport->setClearColor(r, g, b, a);
}

void Sx::QtInterface::QViewportFrame::setRealtime(bool realtime) {
	if ( this->viewport == nullptr ) return;
	this->viewport->setRealtime(realtime);
}

bool Sx::QtInterface::QViewportFrame::isRealtime() const {
	if ( this->viewport == nullptr ) return false;
	return this->viewport->isRealtime();
}

void Sx::QtInterface::QViewportFrame::setWarpCursor(bool warp) {
	if ( this->viewport == nullptr ) return;
	this->viewport->setWarpCursor(warp);
}

bool Sx::QtInterface::QViewportFrame::hasCursorWarp() const {
	if ( this->viewport == nullptr ) return false;
	return this->viewport->hasCursorWarp();
}

bool Sx::QtInterface::QViewportFrame::setFramesPerSecond(unsigned int fps) {
	if ( this->viewport == nullptr ) return false;
	return this->viewport->setFramesPerSecond(fps);
}

unsigned int Sx::QtInterface::QViewportFrame::getFramesPerSecond() const {
	if ( this->viewport == nullptr ) return 0u;
	return this->viewport->getFramesPerSecond();
}

void Sx::QtInterface::QViewportFrame::resizeEvent(QResizeEvent* e) {
	if ( this->viewport == nullptr ) return;
	this->viewport->setGeometry(0, this->toolbarHeight, this->width(), this->height() - this->toolbarHeight);
}

void Sx::QtInterface::QViewportFrame::focusInEvent(QFocusEvent* e) {
	emit gainsFocus(this);
}

bool Sx::QtInterface::QViewportFrame::ConstructToolButton(QToolButton*& button, QToolBar* toolBar, QWidget* parent, const char* objectName, const char* toolTip, const char* slot) {
	if ( button != nullptr ) {
		std::cerr << "[QViewportFrame:ConstructToolButton] Error: Creating new toolbar button over exisitng (memory leak)." << std::endl;
		return false;
	}

	if ( toolBar == nullptr ) {
		std::cerr << "[QViewportFrame:ConstructToolButton] Error: Cannot add tool button to nullptr toolbar." << std::endl;
		return false;
	}

	button = new QToolButton(parent);
	button->setObjectName(objectName);
	button->setToolTip(toolTip);
	parent->connect(button, SIGNAL(clicked()), parent, slot);
	toolBar->addWidget(button);
	return true;
}
